package org.sang.service.impl;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.mysql.cj.core.util.StringUtils;
import org.sang.bean.ConsumeItemConfig;
import org.sang.bean.ConsumeItemConfigExample;
import org.sang.bean.MbrCard;
import org.sang.bean.OrderConsume;
import org.sang.bean.OrderConsumeExample;
import org.sang.bean.StoreInfo;
import org.sang.bean.StoreInfoExample;
import org.sang.common.SnowflakeIdGeneratorUtils;
import org.sang.common.UserUtils;
import org.sang.dto.AddOrderConsumeReqDto;
import org.sang.dto.AddOrderConsumeTypeReqDto;
import org.sang.dto.OrderConsumeRepDto;
import org.sang.exception.ConsumeException;
import org.sang.mapper.ext.ConsumeItemConfigExtMapper;
import org.sang.mapper.ext.OrderConsumeExtMapper;
import org.sang.mapper.ext.StoreInfoExtMapper;
import org.sang.service.IOrderConsumeService;
import org.sang.service.MbrCardService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 〈一句话描述〉
 * 〈功能详细描述〉
 *
 * @author Naughty
 * @version 2018 /4/4
 * @see OrderConsumeServiceImpl
 * @since 1.0
 */
@Service
@Transactional
public class OrderConsumeServiceImpl implements IOrderConsumeService {

    private static final Logger logger = LoggerFactory.getLogger(OrderConsumeServiceImpl.class);
    @Autowired
    private OrderConsumeExtMapper orderConsumeExtMapper;
    @Autowired
    private MbrCardService mbrCardService;
    @Autowired
    private StoreInfoExtMapper storeInfoExtMapper;
    @Autowired
    private ConsumeItemConfigExtMapper consumeItemConfigExtMapper;


    private static Gson gson = new Gson();

    /**
     * 新增.
     */
    @Override
    public OrderConsume insertOrderConsume(OrderConsume orderConsume) {
        try {
            String consumeId = String.valueOf(SnowflakeIdGeneratorUtils.getId());
            orderConsume.setConsumeId(consumeId);
            orderConsume.setCreatedOperator(UserUtils.getCurrentUser().getUsername());
            orderConsume.setUpdateOperator(UserUtils.getCurrentUser().getUsername());
            orderConsume.setCreatedTime(new Date());
            orderConsume.setUpdateTime(new Date());
            orderConsumeExtMapper.insert(orderConsume);
            logger.info("会员{},新增消费记录", gson.toJson(orderConsume));
        } catch (Exception e) {
            logger.error("会员{},新增消费记录异常{}", orderConsume.getCardNumber(), e.getMessage());
            e.printStackTrace();
            throw new ConsumeException("新增消费记录异常");
        }
        return orderConsume;
    }

    /**
     * 按照会员卡号获取列表和余额.
     *
     * @param pageNum  the page num
     * @param pageSize the page size
     * @return map
     */
    @Override
    public Map<String, Object> findOrderConsumeByCardNumberAndBalance(Integer pageNum, Integer pageSize,
                                                                      OrderConsume orderConsume) {

        Page<OrderConsume> pageResult = PageHelper.startPage(pageNum, pageSize);
        OrderConsumeExample orderConsumeExample = new OrderConsumeExample();
        OrderConsumeExample.Criteria criteria = orderConsumeExample.createCriteria();
        criteria.andCardNumberEqualTo(orderConsume.getCardNumber());
        orderConsumeExample.setOrderByClause("consume_time");
        orderConsumeExtMapper.selectByExample(orderConsumeExample);

        //获取会员卡余额
        MbrCard mbrCard = new MbrCard();
        mbrCard.setCardNo(orderConsume.getCardNumber());
        mbrCard.setStoreId(orderConsume.getStoreId());
        MbrCard mbrCard1 = mbrCardService.queryMbrCardByCardNumberAndStore(mbrCard);
        if (Objects.isNull(mbrCard1)) {
            logger.error("会员卡{},门店{}不存在",orderConsume.getCardNumber(),orderConsume.getStoreId());
            throw new ConsumeException("会员卡不存在");
        }

        //获取门店信息信息列表
        List<StoreInfo> storeInfos = storeInfoExtMapper.selectByExample(new StoreInfoExample());
        //获取所有消费项列表
        List<ConsumeItemConfig> consumeItemConfigs = consumeItemConfigExtMapper.selectByExample(new
            ConsumeItemConfigExample());

        List<OrderConsumeRepDto> resultList = Optional.ofNullable(pageResult.getResult())
            .orElse(Lists.newArrayList())
            .stream()
            .filter(Objects::nonNull)
            .map(s -> {
                OrderConsumeRepDto orderConsumeRepDto = new OrderConsumeRepDto();
                orderConsumeRepDto.setCardNumber(s.getCardNumber());
                orderConsumeRepDto.setConsumeId(s.getConsumeId());
                orderConsumeRepDto.setConsumeMoney(s.getConsumeMoney());
                orderConsumeRepDto.setConsumeTime(s.getConsumeTime());
                orderConsumeRepDto.setCreatedOperator(s.getCreatedOperator());
                orderConsumeRepDto.setCreatedTime(s.getCreatedTime());
                orderConsumeRepDto.setItemId(s.getItemId());
                orderConsumeRepDto.setStoreId(s.getStoreId());
                orderConsumeRepDto.setUpdateOperator(s.getUpdateOperator());
                orderConsumeRepDto.setUpdateTime(s.getUpdateTime());
                Optional<StoreInfo> first1 = Optional.ofNullable(storeInfos)
                    .orElse(Lists.newArrayList())
                    .stream()
                    .filter(Objects::nonNull)
                    .filter(i -> i.getStoreId().equals(s.getStoreId()))
                    .findFirst();

                if (first1.isPresent()) {
                    orderConsumeRepDto.setStoreName(first1.get().getStoreName());
                }

                Optional<ConsumeItemConfig> first = Optional.ofNullable(consumeItemConfigs)
                    .orElse(Lists.newArrayList())
                    .stream()
                    .filter(Objects::nonNull)
                    .filter(c -> c.getStoreId().equals(s.getStoreId()) && c.getItemId().equals(s.getItemId()))
                    .findFirst();

                if (first.isPresent()) {
                    orderConsumeRepDto.setItemName(first.get().getItemName());
                }
                return orderConsumeRepDto;
            })
            .collect(Collectors.toList());


        Map<String, Object> result = Maps.newConcurrentMap();
        result.put("result", resultList);
        result.put("total", pageResult.getTotal());
        result.put("balance", String.valueOf(mbrCard1.getBalance()));
        return result;
    }

    /**
     * 批量增加消费记录.
     */
    @Override
    public void addOrderConsumeList(AddOrderConsumeReqDto addOrderConsumeReqDto) {
        //获取卡信息,得到卡的余额 和状态
        String cardNumber = addOrderConsumeReqDto.getCardNumber();
        String storeId = addOrderConsumeReqDto.getStoreId();
        MbrCard mbrCard = new MbrCard();
        mbrCard.setStoreId(storeId);
        mbrCard.setCardNo(cardNumber);
        MbrCard mbc = mbrCardService.queryMbrCardByCardNumberAndStore(mbrCard);
        if (Objects.isNull(mbc)) {
            throw new ConsumeException("会员卡不存在");
        }
        if ("0".equals(mbc.getState())) {
            throw new ConsumeException("会与卡无效");
        }
        int totalConsumeMoney = Optional.ofNullable(addOrderConsumeReqDto.getConsumeList())
            .orElse(Lists.newArrayList())
            .stream()
            .filter(Objects::nonNull)
            .mapToInt(AddOrderConsumeTypeReqDto::getConsumeMoney)
            .sum();
        if (mbc.getBalance().intValue() <= 0) {
            throw new ConsumeException("会员卡余额为零");
        }
        if (mbc.getBalance().intValue() < totalConsumeMoney) {
            throw new ConsumeException("会员卡余额不足");
        }


        //增加记录
        Stream<OrderConsume> orderConsumeStream = Optional.ofNullable(addOrderConsumeReqDto.getConsumeList())
            .orElse(Lists.newArrayList())
            .stream()
            .filter(Objects::nonNull)
            .map(s -> {
                OrderConsume orderConsume = new OrderConsume();
                String consumeId = null;
                try {
                    consumeId = String.valueOf(SnowflakeIdGeneratorUtils.getId());
                } catch (Exception e) {
                    logger.error("生成消费记录编号失败");
                    throw new ConsumeException("新增消费记录异常");
                }
                orderConsume.setConsumeId(consumeId);
                orderConsume.setCreatedOperator(UserUtils.getCurrentUser().getUsername());
                orderConsume.setUpdateOperator(UserUtils.getCurrentUser().getUsername());
                orderConsume.setCreatedTime(new Date());
                orderConsume.setUpdateTime(new Date());

                orderConsume.setCardNumber(cardNumber);
                orderConsume.setItemId(s.getItemId());
                orderConsume.setConsumeMoney(s.getConsumeMoney());
                orderConsume.setStoreId(storeId);
                orderConsume.setConsumeTime(new Date());
                return orderConsume;
            });
        orderConsumeStream.forEach(s -> {
            orderConsumeExtMapper.insert(s);
        });

        try {

            mbc.setBalance(mbc.getBalance() - totalConsumeMoney);
            mbc.setUpdateTime(new Date());
            mbc.setUpdateOperator(UserUtils.getCurrentUser().getUsername());
            logger.info("门店{},会员卡{},更新余额{}", storeId, cardNumber, mbc.getBalance().intValue());
            mbrCardService.updateMbrCardBalance(mbc);
        } catch (Exception e) {
            logger.error("增加消费记录失败");
            throw new ConsumeException("新增消费记录失败");
        }
    }

    /**
     * 修改.
     */
    @Override
    public OrderConsume updateOrderConsume(OrderConsume orderConsume) {
        orderConsume.setUpdateOperator(UserUtils.getCurrentUser().getUsername());
        orderConsume.setUpdateTime(new Date());
        orderConsumeExtMapper.updateOrderConsumeByConsumeId(orderConsume);
        logger.info("消费记录{},更新信息", orderConsume.getConsumeId());
        return orderConsume;
    }

    /**
     * 删除.
     */
    @Override
    public void deleteOrderConsume(String consumeId) {
        try {
            OrderConsumeExample orderConsumeExample = new OrderConsumeExample();
            orderConsumeExample.createCriteria().andConsumeIdEqualTo(consumeId);
            orderConsumeExtMapper.deleteByExample(orderConsumeExample);
            logger.info("消费记录{},删除", consumeId);
        } catch (Exception e) {
            logger.error("消费记录{},删除消费记录异常{}", consumeId, e.getMessage());
            e.printStackTrace();
            throw new ConsumeException("删除消费记录异常");
        }
    }

    @Override
    public Page<OrderConsume> findStoreInfoListByPage(Integer pageNum, Integer pageSize, OrderConsume orderConsume) {
        Page<OrderConsume> result = PageHelper.startPage(pageNum, pageSize);
        OrderConsumeExample orderConsumeExample = new OrderConsumeExample();
        OrderConsumeExample.Criteria criteria = orderConsumeExample.createCriteria();

        if (!StringUtils.isNullOrEmpty(orderConsume.getStoreId())) {
            criteria.andStoreIdEqualTo(orderConsume.getStoreId());
        }
        if (!StringUtils.isNullOrEmpty(orderConsume.getCardNumber())) {
            criteria.andCardNumberEqualTo(orderConsume.getCardNumber());
        }
        if (!StringUtils.isNullOrEmpty(orderConsume.getConsumeId())) {
            criteria.andConsumeIdEqualTo(orderConsume.getConsumeId());
        }
        if (!StringUtils.isNullOrEmpty(orderConsume.getItemId())) {
            criteria.andItemIdEqualTo(orderConsume.getItemId());
        }

        orderConsumeExtMapper.selectByExample(orderConsumeExample);

        return result;
    }

    /**
     * 查找单个对象.
     */
    @Override
    public OrderConsume queryOrderConsume(String consumeId) {
        logger.info("消费记录{},获取消费信息", consumeId);
        OrderConsumeExample orderConsumeExample = new OrderConsumeExample();
        orderConsumeExample.createCriteria().andConsumeIdEqualTo(consumeId);
        List<OrderConsume> list = orderConsumeExtMapper.selectByExample(orderConsumeExample);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        } else {
            return list.get(0);
        }
    }

}
